#ifndef LOGSTREAM_H
#define LOGSTREAM_H

#include "LogBuffer.hpp"

namespace Logger
{
    // 因为统一使用const char\*+int len深入底层简化开发，定义LogTemplate通用存数据类绑定const char*+int len
    class LogTemplate
    {
    public:
        LogTemplate(const char *data, int len) : data_(data), len_(len)
        {
        }

        const char *data_;
        int len_;
    };

    // LogStream作为中间层，重载多种运算符，将Logger LoggerImpl数据写入LogBuffer
    class LogStream
    {
    public:
        // 怪异的写法：
        // 1.需要LogBuffer<>不依赖对象的变量初始化大小，定义为static
        // 2.LogBuffer<>是模板类，模板参数需要定义为static constexpr
        // LogBuffer.h：static constexpr int sSmallBufferSize = 4000;
        // 3.类名::静态变量使用静态变量，模板类类名又需要一个模板参数，形成套娃
        // 这里随便使用一个符合模板参数类型的值来补全类名：LogBuffer<0>::sSmallBufferSize

        // 优化：
        // 实际上可以把static constexpr变量定义到全局而不是作为LogBuffer<>的静态变量来使用，写法就会简单
        // 作者这里只是想把语义相关的两者绑定在一起
        using Buffer = LogBuffer<LogBuffer<0>::sSmallBufferSize>;

        const Buffer &getBuffer() const
        {
            return this->buffer_;
        }

        // void appendBuffer(const char *data, int len)
        // {
        //     this->buffer_.append(data, len);
        // }

        // void resetBuffer()
        // {
        //     this->buffer_.reset();
        // }

        // 函数模板+类型萃取+特化重载<<运算符
        template <typename T>
        LogStream &operator<<(T val)
        {
            if constexpr (std::is_same_v<T, bool>)
            {
                this->buffer_.append(val ? "true" : "false", val ? 4 : 5);
            }
            else if constexpr (std::is_same_v<T, char>)
            {
                this->buffer_.append(&val, 1);
            }
            else if constexpr (std::is_integral_v<T>)
            {
                // bool、char，注意这两处理不同
                // short、int、long、long long
                // unsigned short、unsigned int、unsigned long、unsigned long long
                this->intToChar(val);
            }
            else if constexpr (std::is_floating_point_v<T>)
            {
                // float、double
                char buffer[LogBuffer<0>::sSmallBufferSize];
                int len = ::snprintf(buffer, sizeof(buffer), "%.12g", static_cast<double>(val));
                this->buffer_.append(buffer, len);
            }
            else if constexpr (std::is_same_v<T, char *>)
            {
                this->buffer_.append(val, ::strlen(val));
            }
            else if constexpr (std::is_same_v<T, const char *>)
            {
                this->buffer_.append(val, ::strlen(val));
            }
            else if constexpr (std::is_same_v<T, const unsigned char *>)
            {
                this->buffer_.append(reinterpret_cast<const char *>(val), ::strlen(reinterpret_cast<const char *>(val)));
            }
            else if constexpr (std::is_same_v<T, std::string>)
            {
                this->buffer_.append(val.c_str(), val.size());
            }
            else if constexpr (std::is_same_v<T, LogTemplate>)
            {
                this->buffer_.append(val.data_, val.len_);
            }
            // 模板对函数指针推导特殊，用特化
            // else if constexpr (std::is_same_v<T, std::ostream &(*)(std::ostream &)>)
            // {
            //     this->buffer_.append("\n", 1); // 替代 std::endl 的效果（仅换行）
            // }
            else
            {
                // 任何类型sizeof(T) >= 1，为0时断言
                static_assert(sizeof(T) == 0, "Unsupported type for LogStream::operator<<");
            }

            return *this;
        }

        using streamFuncP = std::ostream &(*)(std::ostream &);
        LogStream &operator<<(streamFuncP funcP)
        {
            this->buffer_.append("\n", 1); // 替代 std::endl 的效果（仅换行）
            return *this;
        }

    private:
        static const int sMaxNumLen = 32; // 最大数字长度，static const类内初始化
        // 函数模板转换整型->char*
        template <typename T>
        void intToChar(T num)
        {
            if (this->buffer_.avail() < sMaxNumLen)
            {
                return; // 可优化：继续处理错误
            }

            char *begin = this->buffer_.getCur();
            char *cur = begin;
            const char digits[] = "9876543210123456789";
            const char *digit = digits + 9; // 定位到0，余数是正数就往右取，负数往左取，统一处理
            bool isNagetive = num < 0 ? true : false;
            if (num == 0) // 不使用do-while注意额外判断
            {
                *cur = '0';
                cur++;
            }
            while (num != 0)
            {
                int remain = static_cast<int>(num % 10);
                *cur = digit[remain];
                cur++;

                num /= 10;
            }
            if (isNagetive == true)
            {
                *cur = '-';
                cur++;
            }
            *cur = '\0';
            std::reverse(begin, cur); // 前面是低位到高位存，反转

            // 记得维护缓冲区变量
            int len = static_cast<int>(cur - begin);
            this->buffer_.add(len);
        }

        Buffer buffer_;
    };
} // namespace Logger

#endif // LOGSTREAM_H